#-------------------------------------------------------------------------------
# Copyright (c) 2012 Huseyin BIYIK.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the GNU Public License v3.0
# which accompanies this distribution, and is available at
# http://www.gnu.org/licenses/gpl.html
# 
# Contributors:
#     Huseyin BIYIK - initial API and implementation
#-------------------------------------------------------------------------------
from defs import logger, null_func
import streaming
debug = 3

class call():
	def __init__(self, id, fromaddr, fromport, toaddr, toport,stream=False):
		self.id = id
		self.active=False
		self.fromaddr = fromaddr
		self.fromport = fromport
		self.toaddr = toaddr
		self.toport = toport
		self.differences_down = [0]
		self.differences_up = [0]
		self.stream = streaming.stream(id)

	def create_buffer(self):
		self.buffer=streaming.buffer(self.stream)
	
	def set_id(self, id):
		self.id=id
		for stype in streaming.stypes:
			if hasattr(self.stream, stype):
				getattr(self.stream, stype).callid = id		

	def reverse(self):
		fromaddr = self.fromaddr
		fromport = self.fromport
		self.fromaddr = self.toaddr
		self.fromport = self.toport
		self.toaddr = fromaddr
		self.toport = fromport
		return self 
	
	def close(self):
		self.buffer.close()
		del self
		
class manager():
	def __init__(self, sender, interfaces,loopback):
		self.loopback=loopback
		self.calls = {}
		streaming.stypes = interfaces.keys()
		## set stype_chunk=False for each type
		## set stype_reader(q,stype,flag,sfunc) for each type
		for stype in streaming.stypes:
			setattr(self, stype + "_chunk", 0)
			if not self.loopback:
				setattr(self,"reader_"+stype,streaming.reader(sender,self,stype,interfaces[stype]["in"]))

	def close(self):
		logger.info("Closing call manager")
		for stype in streaming.stypes:
			if not self.loopback:
				getattr(self,"reader_"+stype).close()
		for cllid in self.calls.keys():
			self.terminate_call(self.calls[cllid])
		del self	
	def add_call(self, cll):
		if not self.is_call(cll.id):
			self.calls[cll.id] = cll
			return self.calls[cll.id]
		
	def activate_call(self,cll):
		if self.is_call(cll.id) and not self.is_active(cll.id):
			self.calls[cll.id].active=True
			if not hasattr(cll,"buffer"):
				self.calls[cll.id].create_buffer()
			self.set_stream()
			return self.calls[cll.id]
		else:
			logger.info("Call '%s' is either already active or does not exist", cll.id)

	def remove_call(self, cll):
		if self.is_call(cll.id):
			if len(self.calls[cll.id].stream.get_types()) == 0 :
				self.terminate_call(cll)
			else:
				self.set_stream()
			return True
		else:
			return False
		

	def terminate_call(self,cll):
		self.calls.pop(cll.id)
		self.set_stream()
		cll.close()
		logger.info("Call '%s' is removed", cll.id)

		
	def set_stream(self):
		for stype in streaming.stypes:
			if self.num_of_streams(stype):
				setattr(self,stype+"_chunk",100)
			else:
				setattr(self,stype+"_chunk",0)
		
	def num_of_streams(self,sname):
		num = 0
		for cllid in self.calls:
			if self.calls[cllid].stream.get_type_param(sname,"enabled"):
				num += 1
		return num

	def is_call(self, callid):
		if callid in self.calls.keys():
			return True
		else:
			logger.debug("No call '%s'", callid)
			return False
	def is_active(self, callid):
		if self.is_call(callid) and self.calls[callid].active:
			return True
		else:
			logger.debug("No active call '%s'", callid)
		
